﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WCAD.Kean
{
    public class ExtendLines
    {
        [CommandMethod("EXL")]

        public void EXL()

        {

            Document doc =

              Application.DocumentManager.MdiActiveDocument;

            Database db = doc.Database;

            Editor ed = doc.Editor;



            // Call a function to return a selection set of lines



            SelectionSet ss =

              SelectLines(ed, "\nSelect lines to extend: ");

            if (ss != null)

            {

                // Start our transaction



                Transaction tr =

                  db.TransactionManager.StartTransaction();

                using (tr)

                {

                    // Edit each of the selected lines



                    foreach (SelectedObject so in ss)

                    {

                        // We're assuming only lines are in the selection-set

                        // Could also use a more defensive approach and

                        // use a dynamic cast (Line ln = xxx as Line;)



                        Line ln =

                          (Line)tr.GetObject(

                            so.ObjectId,

                            OpenMode.ForWrite

                          );



                        // We'll extend our line by a quarter of the

                        // existing length in each direction



                        Vector3d ext = ln.Delta / 4;



                        // First the start-point



                        ln.Extend(true, ln.StartPoint - ext);



                        // And then the end-point



                        ln.Extend(false, ln.EndPoint + ext);

                    }



                    // Mustn't forget to commit



                    tr.Commit();

                }

            }

        }



        [CommandMethod("SHL")]

        public void SHL()

        {

            Document doc =

              Application.DocumentManager.MdiActiveDocument;

            Database db = doc.Database;

            Editor ed = doc.Editor;



            // Call a function to return a selection set of lines



            SelectionSet ss =

              SelectLines(ed, "\nSelect lines to shorten: ");

            if (ss != null)

            {

                // Start our transaction

                // (Needs to be Open/Close to avoid an eInvalidContext

                //  from HandOverTo())



                Transaction tr =

                  db.TransactionManager.StartOpenCloseTransaction();

                using (tr)

                {

                    // Edit each of the selected lines



                    foreach (SelectedObject so in ss)

                    {

                        // We're assuming only curves are in the selection-set

                        // Could also use a more defensive approach and

                        // use a dynamic cast (Curve cur = xxx as Curve;)



                        Curve cur =

                          (Curve)tr.GetObject(

                            so.ObjectId,

                            OpenMode.ForWrite

                          );



                        double sp = cur.StartParam,

                              ep = cur.EndParam,

                              delta = (ep - sp) * 0.25;



                        DoubleCollection dc = new DoubleCollection();

                        dc.Add(sp + delta);

                        dc.Add(ep - delta);

                        DBObjectCollection objs = cur.GetSplitCurves(dc);



                        if (objs.Count == 3)

                        {

                            Entity ent = (Entity)objs[1];

                            cur.HandOverTo(ent, true, true);

                            tr.AddNewlyCreatedDBObject(ent, true);

                            cur.Dispose();

                            objs[0].Dispose();

                            objs[2].Dispose();

                        }

                    }



                    // Mustn't forget to commit



                    tr.Commit();

                }

            }

        }



        // Helper function to select a set of lines



        private SelectionSet SelectLines(Editor ed, string msg)

        {

            // We only want to select lines...



            // Use an options object to specify how the

            // selection occurs (in terms of prompts)



            PromptSelectionOptions pso =

              new PromptSelectionOptions();

            pso.MessageForAdding =

              (string.IsNullOrEmpty(msg) ? "\nSelect lines: " : msg);



            // Use a filter to specify the objects that

            // get included in the selection set



            TypedValue[] tvs =

              new TypedValue[1] {

            new TypedValue(

              (int)DxfCode.Start,

              "LINE"

            )

                };

            SelectionFilter sf = new SelectionFilter(tvs);



            // Perform our restricted selection



            PromptSelectionResult psr = ed.GetSelection(pso, sf);



            if (psr.Status != PromptStatus.OK || psr.Value.Count <= 0)

                return null;



            return psr.Value;

        }
    }
}
